package com.zeng.ssm.service.support.idempotent;

import com.zeng.ssm.api.support.idempotent.DistributedLockService;
import com.whalin.MemCached.MemCachedClient;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * Memcached分布式锁实现
 *
 * @author zengwanlin
 * @date 2021-11-04T10:00
 */
public class MemcachedDistributedLockServiceImpl implements DistributedLockService {

    private final Logger logger = LoggerFactory.getLogger(MemcachedDistributedLockServiceImpl.class);

    private MemCachedClient memCachedClient;

    public void setMemCachedClient(MemCachedClient memCachedClient) {
        this.memCachedClient = memCachedClient;
    }

    @PostConstruct
    public void afterPropertySet() {
        Assert.notNull(memCachedClient, "memCachedClient不能为空");
    }

    @Override
    public boolean setIfAbsent(String key, String value) {
        boolean result = memCachedClient.add(key, value);
        if (logger.isDebugEnabled()) {
            logger.debug("Memcached.setIfAbsent，key[{}]，value[{}]，结果[{}]", new Object[]{key, value, result});
        }
        return result;
    }

    @Override
    public boolean setIfAbsent(String key, String value, long timeout, TimeUnit unit) {
        Date expire = new Date(System.currentTimeMillis() + unit.toMillis(timeout));
        boolean result = memCachedClient.add(key, value, expire);
        if (logger.isDebugEnabled()) {
            logger.debug("Memcached.setIfAbsent，key[{}]，value[{}]，timeout[{}]，结果[{}]", new Object[]{key, value, expire, result});
        }
        return result;
    }

    @Override
    public boolean deleteAnyway(String key) {
        try {
            if (memCachedClient.keyExists(key)) {
                return memCachedClient.delete(key);
            }
            return true;
        } catch (Exception e) {
            logger.warn("Memcached.deleteAnyway异常，" + e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean lock(String key, String value, long timeout) {
        Date expire = new Date(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(timeout));
        boolean result = memCachedClient.add(key, value, expire);
        if (logger.isDebugEnabled()) {
            logger.debug("Memcached加锁，key[{}]，value[{}]，timeout[{}]，结果[{}]", new Object[]{key, value, expire, result});
        }
        return result;
    }

    @Override
    public boolean unlock(String key, String value) {
        boolean result;
        if (StringUtils.equals(value, String.valueOf(memCachedClient.get(key)))) {
            result = memCachedClient.delete(key);
        } else {
            result = true;
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Memcached解锁，key[{}]，value[{}]，结果[{}]", new Object[]{key, value, result});
        }
        return result;
    }

}
